package com.youpai.platform.wallet.service.service.impl;

import com.youpai.platform.common.util.UserContext;
import com.youpai.platform.common.util.id.IdGenerator;
import com.youpai.platform.user.web.entity.dto.UserDTO;
import com.youpai.platform.wallet.exception.ChangeCoinResultException;
import com.youpai.platform.wallet.service.convert.WalletConverter;
import com.youpai.platform.wallet.service.entity.dto.ChangeCoinTransactionDTO;
import com.youpai.platform.wallet.service.entity.po.WalletRecordPO;
import com.youpai.platform.wallet.service.entity.po.WalletPO;
import com.youpai.platform.wallet.service.enums.ChangeCoinTypeEnums;
import com.youpai.platform.wallet.web.entity.dto.MakeTransactionReq;
import com.youpai.platform.wallet.web.entity.resp.ChangeCoinResp;
import com.youpai.platform.wallet.web.enums.ChangeCoinResultEnum;
import com.youpai.platform.wallet.service.mapper.WalletRecordMapper;
import com.youpai.platform.wallet.service.mapper.WalletMapper;
import com.youpai.platform.wallet.service.service.WalletService;
import com.youpai.platform.wallet.service.service.transaction.WalletTransaction;
import com.youpai.platform.wallet.web.entity.dto.ChangeCoinReq;
import com.youpai.platform.wallet.web.entity.dto.WalletLogDTO;
import com.youpai.platform.wallet.web.entity.req.QueryWalletLogReq;
import com.youpai.platform.wallet.web.entity.resp.GetWalletInfoResp;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @date: 2023/2/15
 * @author: Welles
 * @version: 1.0
 * @description: 钱包服务
 */
@Service
public class WalletServiceImpl implements WalletService {

    @Resource
    private WalletMapper walletMapper;
    @Resource
    private WalletRecordMapper walletRecordMapper;
    @Resource
    private WalletTransaction walletTransaction;

    @Override
    public GetWalletInfoResp getWalletInfo() {
        UserDTO userContext = UserContext.getUserContext();
        String uid = userContext.getUid();
        WalletPO walletPO = walletMapper.selectWalletByUid(Long.parseLong(uid));
        double purchasedCoin = walletPO.getOnlyEmployCoin() / 100.00;
        double earnedCoin = walletPO.getWithdrawCoin() / 100.00;
        double totalCoin = (walletPO.getWithdrawCoin() + walletPO.getOnlyEmployCoin()) / 100.00;
        GetWalletInfoResp resp = new GetWalletInfoResp();
        resp.setWalletId(String.valueOf(walletPO.getWalletId()))
                .setUid(uid)
                .setPurchasedCoin(String.valueOf(purchasedCoin))
                .setEarnedCoin(String.valueOf(earnedCoin))
                .setTotalCoin(String.valueOf(totalCoin));
        return resp;
    }

    @Override
    public List<WalletLogDTO> queryWalletLog(QueryWalletLogReq req) {
        UserDTO userContext = UserContext.getUserContext();
        String uid = userContext.getUid();
        List<WalletRecordPO> walletRecordPOS = walletRecordMapper.queryWalletRecordByUid(Long.valueOf(uid), req.getStartTime(), req.getEndTime());
        return WalletConverter.convertWalletLogPO2WalletLogDTO(walletRecordPOS);
    }

    @Override
    public ChangeCoinResp changeCoin(ChangeCoinReq changeCoinReq) {
        ChangeCoinResultEnum checkResult = bizCheckReq(changeCoinReq);
        if (checkResult.code != ChangeCoinResultEnum.SUCCESS.code) {
            return ChangeCoinResp.buildChangeCoinResultByEnum(checkResult);
        }
        WalletPO walletPO = walletMapper.selectWalletByUid(changeCoinReq.getUid());
        if (null == walletPO) {
            return ChangeCoinResp.buildChangeCoinResultByEnum(ChangeCoinResultEnum.WALLET_NOT_EXIST);
        }
        ChangeCoinTransactionDTO changeCoinTransactionDTO = buildChangeCoinTransactionDTO(changeCoinReq, walletPO);
        try {
            walletTransaction.changeCoin(changeCoinTransactionDTO);
        } catch (Exception exception) {
            if (exception instanceof ChangeCoinResultException) {
                ChangeCoinResultException changeCoinResultException = (ChangeCoinResultException) exception;
                return ChangeCoinResp.buildChangeCoinResultByEnum(changeCoinResultException.getChangeCoinResultEnum());
            }
            return ChangeCoinResp.buildChangeCoinResultByEnum(ChangeCoinResultEnum.CHANGE_COIN_ERROR);
        }
        return ChangeCoinResp.buildChangeCoinResultByEnum(ChangeCoinResultEnum.SUCCESS);
    }

    private ChangeCoinTransactionDTO buildChangeCoinTransactionDTO(ChangeCoinReq changeCoinReq, WalletPO walletPO) {
        long onlyEmployCoin = 0L;
        long withdrawCoin = 0L;
        switch (changeCoinReq.getChangeCoinType()) {
            case 1:
            case 2:
            case 3:
                onlyEmployCoin = changeCoinReq.getChangeCoinNumber();
                break;
            case 4:
                withdrawCoin = changeCoinReq.getChangeCoinNumber();
                break;
        }
        return new ChangeCoinTransactionDTO()
                .setUid(changeCoinReq.getUid())
                .setChangeCoinType(changeCoinReq.getChangeCoinType())
                .setSource(changeCoinReq.getSource())
                .setWalletId(walletPO.getWalletId())
                .setOnlyEmployCoin(onlyEmployCoin)
                .setWithdrawCoin(withdrawCoin)
                .setOrderId(changeCoinReq.getOrderId());
    }

    private ChangeCoinResultEnum bizCheckReq(ChangeCoinReq changeCoinReq) {
        // 账户不存在
        if (null == changeCoinReq) {
            return ChangeCoinResultEnum.WALLET_NOT_EXIST;
        }
        // 修改类型
        if (!ChangeCoinTypeEnums.validType(changeCoinReq.getChangeCoinType())) {
            return ChangeCoinResultEnum.CHANGE_TYPE_EMPTY;
        }
        // uid
        if (null == changeCoinReq.getUid()) {
            return ChangeCoinResultEnum.UID_EMPTY;
        }
        // 修改数量
        if (null == changeCoinReq.getChangeCoinNumber()) {
            return ChangeCoinResultEnum.INVALID_CHANGE_NUMBER;
        }
        return ChangeCoinResultEnum.SUCCESS;
    }

    @Override
    public boolean registerWallet(long uid) {
        WalletPO wallet = buildWalletPO(uid);
        return walletMapper.insertWallet(wallet) > 0;
    }

    private WalletPO buildWalletPO(long uid) {
        WalletPO wallet = new WalletPO();
        wallet.setWalletId(IdGenerator.generateId())
                .setWithdrawCoin(0L)
                .setOnlyEmployCoin(0L)
                .setUid(uid);
        return wallet;
    }
}
